home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MYMUD21.ZIP / MMUD21.ZIP / SOURCE / SOURCE.ZIP / MULTI.PAS < prev    next >
Pascal/Delphi Source File  |  1995-01-21  |  14KB  |  609 lines

  1. {$I COPYRGHT.INC}
  2.  
  3. (*---------------------------------------------------------------------------*
  4.    This unit contains all the routines nessecary for the multiuser support
  5.  *---------------------------------------------------------------------------*)
  6.  
  7. Unit Multi;
  8. Interface
  9. Uses Dos,
  10.      MyIO,
  11.      Misc,
  12.      Header,
  13.      Timer,
  14.      BIN_DB,
  15.      NewWorld,
  16.      Out_Proc;
  17.  
  18. Const MaxMudNodes = 511;
  19.  
  20.  
  21. Var LockLevel : Word;
  22.     LockFile  : File;
  23.     LockStats : LongInt;
  24.     LockCalls : LongInt;
  25.     DoubleCalls: LongInt;
  26.  
  27.  
  28.  
  29. Type NodeInfoRecord = Record
  30.        Player       : Integer;
  31.        Room         : Integer;
  32.        Last         : LongInt;
  33.        Note         : String[40];
  34.      End;
  35.      NodeListType   = Array[0..MaxMudNodes] Of NodeInfoRecord;
  36.  
  37. Var TempDir     : PathStr;
  38.     Editor      : ComStr;
  39.     TextPath    : ComStr;
  40.     WorldPath   : ComStr;
  41.     Mynode      : Integer;
  42.     NodeList    : NodeListType;
  43.  
  44. Procedure ReadINI;
  45.  
  46. Procedure GrabNodeNr;
  47. Procedure FreeNode;
  48.  
  49. Procedure UpdateNodeInfo(Current : ContextType);
  50. Procedure GrabUserList;
  51.  
  52.  
  53. Procedure NotifyAllHere(Name : String;T : TextRecord);
  54. Procedure SayToAllHere(Current : ContextType;S : String);
  55. Procedure GeneralRemarkToAllHere(S : String);
  56. Procedure NotifyAll(T : TextRecord);
  57. Procedure SayToAll(S : String);
  58. Procedure SayPrivate(ObjNr : Integer;S : String);
  59.  
  60.  
  61.  
  62. Procedure ShutDownGame;
  63. Function CheckShutDown:Boolean;
  64.  
  65. Function CheckResetMe:Boolean;
  66. Procedure ResetPlayerObj(ObjNr : Integer);
  67.  
  68. Function CheckMail:Boolean;
  69.  
  70. Procedure ReadMail;
  71. Function IsAlive(ObjNr : Integer):Boolean;
  72.  
  73. Procedure Lock(Reason : String);
  74. Procedure UnLock;
  75. Procedure ShowLockStat;
  76.  
  77. Type StatusTypes = (SetSem,DelSem,WaitSem);
  78.      SemName     = String[8];
  79.  
  80. Procedure Semafore(Name : SemName;Status : StatusTypes);
  81.  
  82. Implementation
  83.  
  84. Procedure Semafore(Name : SemName;Status : StatusTypes);
  85. Var Tmp     : file;
  86.     TimeOut : TimerObject;
  87. Begin
  88. Case Status Of
  89.  SetSem : Begin
  90.           Assign(Tmp,TempDir+Name+'.SEM');
  91.           Rewrite(Tmp);
  92.           Close(Tmp);
  93.           If IoResult<>0 Then;
  94.           End;
  95.  DelSem : Begin
  96.           Assign(Tmp,TempDir+Name+'.SEM');
  97.           Erase(Tmp);
  98.           End;
  99.  WaitSem: Begin
  100.           TimeOut.SetTimer(50);
  101.           Repeat
  102.           Until (Not ExistFile(TempDir+Name+'.SEM')) Or TimeOut.TimeUp;
  103.           If ExistFile(TempDir+Name+'.SEM')
  104.              Then Semafore(Name,DelSem);
  105.           End;
  106. End; {Case}
  107. End;
  108.  
  109. (*--------------------------------------------------------------------------*)
  110. Procedure GrabNodeNr;
  111. Var Search : SearchRec;
  112.     Tmp    : File;
  113. Begin
  114. MyNode:=1;
  115. FindFirst(TempDir+'InUse.'+Nr2Str(MyNode),AnyFile,Search);
  116. While (DosError=0) And (MyNode<=MaxMudNodes) Do
  117.  Begin
  118.  Inc(MyNode);
  119.  FindFirst(TempDir+'InUse.'+Nr2Str(MyNode),AnyFile,Search);
  120.  End;
  121.  
  122. If MyNode>MaxMudNodes
  123.    Then MyNode:=NOTHING
  124.    Else Begin
  125.         Assign(Tmp,TempDir+'InUse.'+Nr2Str(MyNode));
  126.         Rewrite(Tmp);
  127.         Close(Tmp);
  128.         If IoResult<> 0 Then;
  129.         End;
  130. End;
  131.  
  132. (*--------------------------------------------------------------------------*)
  133. Procedure FreeNode;
  134. Var Tmp   : File;
  135.     Count : Byte;
  136. Begin
  137. Count:=0;
  138. Repeat
  139.  Assign(Tmp,TempDir+'InUse.'+Nr2Str(MyNode));
  140.  Erase(Tmp);
  141.  If IoResult<>0
  142.     Then Inc(Count);
  143. Until (IoResult=0) Or (Count>3);
  144. End;
  145.  
  146. (*--------------------------------------------------------------------------*)
  147. Procedure ReadINI;
  148. Var IniName : ComStr;
  149.     Ini     : Text;
  150.     Sem     : File;
  151.     Count   : Byte;
  152.     Tmp     : ContextType;
  153.     P       : Byte;
  154.     Ok      : Boolean;
  155. Begin
  156. ININame:=ParamStr(1);
  157. If Pos('.',ININame)>0
  158.    Then ININame:=Copy(ININame,1,Pos('.',ININame)-1);
  159.  
  160. If Not ExistFile(IniName+'.INI')
  161.    Then Begin
  162.         My_Write('Database not found. Create new database? [y/N]:');
  163.         If Upcase(My_ReadKey)='Y'
  164.            Then CreateNewWorld(IniName)
  165.            Else Halt;
  166.         End;
  167.  
  168. WorldPath:=IniName;
  169. While (WorldPath<>'') And (Not (WorldPath[Length(WorldPath)] in ['\',':'])) Do
  170.  Dec(WorldPath[0]);
  171. CompletePath(WorldPath);
  172.  
  173. Count:=0;
  174. Repeat
  175.   Assign(INI,ININame+'.INI');
  176.   Reset(INI);
  177.   Ok:=IoResult=0;
  178.   If Not Ok
  179.      Then Begin
  180.           Inc(Count);
  181.           My_Delay(500);
  182.           End;
  183. Until Ok Or (Count>3);
  184. If Count>3
  185.    Then Halt(150);
  186. ReadLn(Ini,TempDir);
  187. ReadLn(Ini,Editor);
  188. ReadLn(Ini,TextPath);
  189. Close(Ini);
  190. If IoResult<>0
  191.    Then Halt(103);
  192.  
  193. P:=Pos('~',TempDir);
  194. if P>0
  195.    Then Begin
  196.         Delete(TempDir,P,1);
  197.         Insert(HomeDir,TempDir,P);
  198.         End;
  199.  
  200. P:=Pos('~',TextPath);
  201. if P>0
  202.    Then Begin
  203.         Delete(TextPath,P,1);
  204.         Insert(HomeDir,TextPath,P);
  205.         End;
  206.  
  207. Tmp.Player:=NOTHING;
  208.  
  209. CompletePath(TextPath);
  210. If Not ExistFile(TextPath+'*.*')
  211.    Then Begin
  212.         My_WriteLn('TextDir doesn''t exist: '+TextPath);
  213.         Halt(0);
  214.         End;
  215.  
  216. CompletePath(TempDir);
  217. If Not ExistFile(TempDir+'*.*')
  218.    Then Begin
  219.         My_WriteLn('TempDir doesn''t exist: '+TempDir);
  220.         Halt(0);
  221.         End;
  222.  
  223. If Not ExistFile(TempDir+'MUDLOCK.SEM')
  224.    Then Begin
  225.         Assign(Sem,TempDir+'MUDLOCK.SEM');
  226.         Rewrite(Sem,1);
  227.         Close(Sem);
  228.         If IoResult<>0
  229.            Then;
  230.         End;
  231.  
  232. If Not ExistFile(Editor)
  233.    Then Editor:='';
  234.  
  235. UpdateNodeInfo(Tmp);
  236. End;
  237.  
  238. (*--------------------------------------------------------------------------*)
  239. Procedure UpdateNodeInfo(Current : ContextType);
  240. Var NodeInfo : NodeInfoRecord;
  241.     Tmp      : File of NodeInfoRecord;
  242.     D        : DateTime;
  243.     Dum      : Word;
  244. Begin
  245. NodeInfo.Player:=Current.Player;
  246. NodeInfo.Room:=Current.Room;
  247. NodeInfo.Note:=Current.Note;
  248.  
  249. GetTime(D.Hour,D.Min,D.Sec,dum);
  250. GetDate(D.Year,D.Month,D.Day,Dum);
  251. PackTime(D,NodeInfo.Last);
  252.  
  253. Lock('Update node info');
  254. FileMode:=ReadWrite+ShareDenyAll;
  255. Assign(Tmp,TempDir+'NODEINFO.DAT');
  256. Reset(Tmp);
  257. If IoResult<>0
  258.    Then Rewrite(Tmp);
  259. Seek(Tmp,MyNode);
  260. Write(Tmp,NodeInfo);
  261. Close(Tmp);
  262. If IoResult<>0
  263.    Then;
  264. UnLock;
  265. End;
  266.  
  267.  
  268. (*--------------------------------------------------------------------------*)
  269. Procedure GrabUserList;
  270. Var Tmp      : File;
  271.     NodeInfo : NodeInfoRecord;
  272.     RR       : Word;
  273. Begin
  274. Lock('Nodelist again');
  275. FillChar(NodeList,SizeOf(NodeList),#00);
  276. FileMode:=ReadOnly+ShareDenyNone;
  277. Assign(Tmp,TempDir+'NODEINFO.DAT');
  278. Reset(Tmp,1);
  279. BlockRead(Tmp,NodeList,SizeOf(NodeList),RR);
  280. Close(Tmp);
  281. Unlock;
  282.  
  283. End;
  284.  
  285.  
  286. (*--------------------------------------------------------------------------*)
  287. Function IsAlive(ObjNr : Integer):Boolean;
  288. Var C: Word;
  289. Begin
  290. GrabUserList;
  291. C:=0;
  292. While (C<=MaxMudNodes) And (ObjNr<>NodeList[C].Player) Do
  293.  Inc(C);
  294. IsAlive:=(C<MaxMudNodes) {And (C<>MyNode)};
  295. End;
  296.  
  297. (*--------------------------------------------------------------------------*)
  298. Procedure NotifyAllHere(Name : String;T : TextRecord);
  299. Var out : File;
  300.     Len : Word;
  301.     C   : Word;
  302.     RW  : Word;
  303.     Tries : Word;
  304. Begin
  305. GrabUserList;
  306.  
  307.  
  308. If T[0]=#00
  309.    Then Exit;
  310.  
  311. Len:=0;
  312. While T[Len]<>#00 Do
  313.  Inc(Len);
  314.  
  315. If Name<>''
  316.    Then Begin
  317.         Move(T[0],T[Length(Name)],Len);
  318.         Len:=Len+Length(Name);
  319.         Move(Name[1],T[0],Length(Name));
  320.         End;
  321. Lock('Send message all here');
  322. For C:=0 To MaxMudNodes Do
  323.  Begin
  324.  If (NodeList[C].Player>0) And (C<>MyNode) And
  325.     (NodeList[C].Room=NodeList[MyNode].Room)
  326.     Then Begin
  327.          FileMode:=ReadWrite+ShareDenyAll;
  328.          Assign(Out,TempDir+'Message.'+Nr2Str(C));
  329.          Reset(Out,1);
  330.          If IoResult<>0
  331.             Then Rewrite(Out,1);
  332.          Seek(Out,FileSize(Out));
  333.          BlockWrite(Out,T,SizeOf(T),RW);
  334.          Close(Out);
  335.          If IoResult<>0
  336.             Then;
  337.          End;
  338.  End;
  339. Unlock;
  340. End;
  341.  
  342.  
  343. (*--------------------------------------------------------------------------*)
  344. Procedure NotifyAll(T : TextRecord);
  345. Var out : File;
  346.     C   : Word;
  347.     RW  : Word;
  348.  
  349. Begin
  350. GrabUserList;
  351.  
  352.  
  353. If T[0]=#00
  354.    Then Exit;
  355. Lock('Notify all everywhere');
  356. For C:=0 To MaxMudNodes Do
  357.  Begin
  358.  If (NodeList[C].Player>0) And (C<>MyNode)
  359.     Then Begin
  360.          FileMode:=ReadWrite+ShareDenyAll;
  361.          Assign(Out,TempDir+'Message.'+Nr2Str(C));
  362.          Reset(Out,1);
  363.          If IoResult<>0
  364.             Then Rewrite(Out,1);
  365.          Seek(Out,FileSizE(Out));
  366.          BlockWrite(Out,T,SizeOf(T),RW);
  367.          Close(Out);
  368.          If IoResult<>0
  369.             Then;
  370.          End;
  371.  End;
  372. UnLock;
  373. End;
  374.  
  375.  
  376. (*--------------------------------------------------------------------------*)
  377. Procedure PrivateMsg(ToPlayer : Word;T : TextRecord);
  378. Var Out   : File;
  379.     ToNode: Word;
  380.     RW    : Word;
  381.  
  382. Begin
  383. GrabUserList;
  384.  
  385. ToNode:=0;
  386. While (ToNode<=MaxMudNodes) And (NodeList[ToNode].Player<>ToPlayer) Do
  387.  Inc(ToNode);
  388.  
  389. If ToNode>MaxMudNodes
  390.    Then Exit;
  391.  
  392. If T[0]=#00
  393.    Then Exit;
  394.  
  395. Lock('Prv. Message');
  396. If (NodeList[ToNode].Player>0) And (ToNode<>MyNode)
  397.    Then Begin
  398.         FileMode:=ReadWrite+ShareDenyAll;
  399.         Assign(Out,TempDir+'Message.'+Nr2Str(ToNode));
  400.         Reset(Out,1);
  401.         If IoResult<>0
  402.            Then Rewrite(Out,1);
  403.         Seek(Out,FileSizE(Out));
  404.         BlockWrite(Out,T,SizeOf(T),RW);
  405.         Close(Out);
  406.         If IoResult<>0
  407.            Then;
  408.         End;
  409. Unlock;
  410. End;
  411.  
  412.  
  413. (*--------------------------------------------------------------------------*)
  414. Procedure SayPrivate(ObjNr : Integer;S : String);
  415. Var T : TextRecord;
  416. Begin
  417. FillChar(T,SizeOf(T),#00);
  418. Move(S[1],T[0],Length(S));
  419. PrivateMsg(ObjNr,T);
  420. End;
  421.  
  422. (*--------------------------------------------------------------------------*)
  423. Procedure SayToAllHere(Current : ContextType;S : String);
  424. Var T : TextRecord;
  425. Begin
  426. FillChar(T,SizeOf(T),#00);
  427. Move(S[1],T[0],Length(S));
  428. NotifyAllHere(Current.PlayerName,T);
  429. End;
  430.  
  431. Procedure SayToAll(S : String);
  432. Var T : TextRecord;
  433. Begin
  434. FillChar(T,SizeOf(T),#00);
  435. Move(S[1],T[0],Length(S));
  436. NotifyAll(T);
  437. End;
  438.  
  439.  
  440. (*--------------------------------------------------------------------------*)
  441. Procedure GeneralRemarkToAllHere(S : String);
  442. Var T : TextRecord;
  443. Begin
  444. FillChar(T,SizeOf(T),#00);
  445. Move(S[1],T[0],Length(S));
  446. NotifyAllHere('',T);
  447. End;
  448.  
  449.  
  450.  
  451. (*--------------------------------------------------------------------------*)
  452. Function CheckMail:Boolean;
  453. Var S : SearchRec;
  454. Begin
  455. FindFirst(TempDir+'MESSAGE.'+Nr2Str(MyNode),AnyFile,S);
  456. CheckMail:=DosError=0;
  457. End;
  458.  
  459. (*--------------------------------------------------------------------------*)
  460. Procedure ResetPlayerObj(ObjNr : Integer);
  461. Var Cnt : Integer;
  462.     Tmp : File;
  463. Begin
  464. Cnt:=0;
  465. While (Cnt<=MaxMudNodes) And (NodeList[Cnt].Player<>ObjNr) Do
  466.  Inc(Cnt);
  467.  
  468. If Cnt>MaxMudNodes
  469.    Then Exit;
  470. Assign(Tmp,TempDir+'RESET.'+Nr2Str(Cnt));
  471. Rewrite(Tmp,1);
  472. Close(Tmp);
  473. If IoResult<>0
  474.    Then;
  475. End;
  476.  
  477.  
  478. (*--------------------------------------------------------------------------*)
  479. Function CheckResetMe:Boolean;
  480. Var S  : SearchRec;
  481.     Tmp: File;
  482.     Ok : Boolean;
  483. Begin
  484. FindFirst(TempDir+'RESET.'+Nr2Str(MyNode),AnyFile,S);
  485. Ok:=DosError=0;
  486. CheckResetMe:=Ok;
  487. If Ok
  488.    Then Begin
  489.         Assign(Tmp,TempDir+'RESET.'+Nr2Str(MyNode));
  490.         Erase(Tmp);
  491.         if IoResult<>0
  492.            Then;
  493.         End;
  494. End;
  495.  
  496. (*--------------------------------------------------------------------------*)
  497. Function CheckShutDown:Boolean;
  498. Var S : SearchRec;
  499. Begin
  500. FindFirst(TempDir+'SHUTDOWN.SEM',AnyFile,S);
  501. CheckShutDown:=DosError=0;
  502. End;
  503.  
  504. (*--------------------------------------------------------------------------*)
  505. Procedure ShutDownGame;
  506. Var Tmp : File;
  507. Begin
  508. Assign(Tmp,TempDir+'SHUTDOWN.SEM');
  509. Rewrite(Tmp);
  510. Close(Tmp);
  511. If IoResult<>0 Then;
  512. End;
  513.  
  514. (*--------------------------------------------------------------------------*)
  515. Procedure ReadMail;
  516. Var Inp : File of TextRecord;
  517.     T   : TextRecord;
  518. Begin
  519. FileMode:=ReadOnly+ShareDenyNone;
  520. Lock('Read mail');
  521. Assign(Inp,TempDir+'MESSAGE.'+Nr2Str(MyNode));
  522. Rename(Inp,TempDir+'HANDLED.'+Nr2Str(MyNode));
  523. Unlock;
  524.  
  525. Reset(Inp);
  526. While Not Eof(Inp) Do
  527.  Begin
  528.  Read(Inp,T);
  529.  WriteText(T);
  530.  End;
  531. Close(Inp);
  532. Erase(Inp);
  533. If IoResult<>0
  534.    Then Exit;
  535. End;
  536.  
  537.  
  538. (*--------------------------------------------------------------------------*)
  539.  
  540.  
  541. Procedure Lock(Reason : String);
  542. Var Ok      : Boolean;
  543.     IOErr   : Integer;
  544.     TimeOut : TimerObject;
  545. Begin
  546. Inc(LockCalls);
  547. If LockLevel>0
  548.    Then Begin
  549.         Inc(LockLevel);
  550.         Inc(DoubleCalls);
  551.         Exit
  552.         End
  553.    Else LockLevel:=1;
  554.  
  555. FileMode:=ReadOnly+ShareDenyAll;
  556. Assign(LockFile,TempDir+'MUDLOCK.SEM');
  557. TimeOut.SetTimer(150);
  558. Repeat
  559.   Reset(LockFile,1);
  560.   IOErr:=IoResult;
  561.   Ok:=IoErr=0;
  562.   If Not Ok
  563.      Then Begin
  564.           Inc(LockStats);
  565.           {My_Beep;}
  566.           My_Delay(300+Random(100));
  567.           End;
  568. Until OK or TimeOut.TimeUp;
  569. If Not Ok
  570.    Then begin
  571.         My_WriteLn('ERROR: '+Reason);
  572.         HALT(100);
  573.         End;
  574. End;
  575.  
  576. (*--------------------------------------------------------------------------*)
  577. Procedure UnLock;
  578. Var Regs    : Registers;
  579. Begin
  580. If LockLevel>1
  581.    then Begin
  582.         Dec(LockLevel);
  583.         Exit;
  584.         End
  585.    Else LockLevel:=0;
  586. Close(LockFile);
  587. End;
  588.  
  589. Procedure ShowLockStat;
  590. Begin
  591. My_WriteLn('Current lock statistics:');
  592. My_WriteLn('  LockLevel  : '+Nr2Str(LockLevel));
  593. My_WriteLn('  LockStats  : '+Nr2Str(LockStats));
  594. My_WriteLn('  LockCalls  : '+Nr2Str(LockCalls));
  595. My_WriteLn('  DoubleCalls: '+Nr2Str(DoubleCalls));
  596. End;
  597.  
  598.  
  599.  
  600. Begin
  601. FillChar(NodeList,SizeOf(NodeList),#00);
  602. MyNode:=0;
  603. LockLevel:=0;
  604. LockCalls:=0;
  605. LockStats:=0;
  606. DoubleCalls:=0;
  607. End.
  608.  
  609.